<!doctype html>
<html lang="en" class="page-type-section">
<head prefix="og: http://ogp.me/ns#">
<meta charset="utf-8">
<title>2.3.21 - FreeMarker 手册</title>
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta name="format-detection" content="telephone=no">
<meta property="og:site_name" content="FreeMarker 手册">
<meta property="og:title" content="2.3.21">
<meta property="og:locale" content="en_US">
<meta property="og:url" content="http://freemarker.org/docs/versions_2_3_21.html">
<link rel="canoical" href="http://freemarker.org/docs/versions_2_3_21.html">
<link rel="icon" href="favicon.png" type="image/png">
<link rel="stylesheet" type="text/css" href="docgen-resources/docgen.min.css">
</head>
<body itemscope itemtype="https://schema.org/Code">
    <meta itemprop="url" content="http://freemarker.org/docs/">
    <meta itemprop="name" content="FreeMarker 手册">

  <!--[if lte IE 9]>
  <div style="background-color: #C00; color: #fff; padding: 12px 24px;">Please use a modern browser to view this website.</div>
  <![endif]--><div class="header-top-bg"><div class="site-width header-top"><a class="logo" href="http://freemarker.org" role="banner">            <img itemprop="image" src="logo.png" alt="FreeMarker">
</a><ul class="tabs"><li><a href="http://freemarker.org/">Home</a></li><li class="current"><a href="index.html">Manual</a></li><li><a class="external" href="http://freemarker.org/docs/api/index.html">Java API</a></li></ul><ul class="secondary-tabs"><li><a class="tab icon-heart" href="http://freemarker.org/contribute.html" title="Contribute"><span>Contribute</span></a></li><li><a class="tab icon-bug" href="https://sourceforge.net/p/freemarker/bugs/new/" title="Report a Bug"><span>Report a Bug</span></a></li><li><a class="tab icon-download" href="http://freemarker.org/freemarkerdownload.html" title="Download"><span>Download</span></a></li></ul></div></div><div class="header-bottom-bg"><div class="site-width search-row"><a href="toc.html" class="navigation-header">Manual</a><div class="navigation-header"></div></div><div class="site-width breadcrumb-row"><ul class="breadcrumb" itemscope itemtype="http://schema.org/BreadcrumbList"><li class="step-0" itemprop="itemListElement" itemscope itemtype="http://schema.org/ListItem"><a class="label" itemprop="item" href="toc.html"><span itemprop="name">FreeMarker 手册</span></a></li><li class="step-1" itemprop="itemListElement" itemscope itemtype="http://schema.org/ListItem"><a class="label" itemprop="item" href="app.html"><span itemprop="name">附录</span></a></li><li class="step-2" itemprop="itemListElement" itemscope itemtype="http://schema.org/ListItem"><a class="label" itemprop="item" href="app_versions.html"><span itemprop="name">版本历史</span></a></li><li class="step-3" itemprop="itemListElement" itemscope itemtype="http://schema.org/ListItem"><a class="label" itemprop="item" href="versions_2_3_21.html"><span itemprop="name">2.3.21</span></a></li></ul><div class="bookmarks" title="Bookmarks"><span class="sr-only">Bookmarks:</span><ul class="bookmark-list"><li><a href="alphaidx.html">Alpha. index</a></li><li><a href="gloss.html">Glossary</a></li><li><a href="dgui_template_exp.html#exp_cheatsheet">Expressions</a></li><li><a href="ref_builtins_alphaidx.html">?builtins</a></li><li><a href="ref_directive_alphaidx.html">#directives</a></li><li><a href="ref_specvar.html">.spec_vars</a></li><li><a href="app_faq.html">FAQ</a></li></ul></div></div></div>    <div class="main-content site-width">
      <div class="content-wrapper">
  <div id="table-of-contents-wrapper" class="col-left">
      <script>var breadcrumb = ["FreeMarker 手册","附录","版本历史","2.3.21"];</script>
      <script src="toc.js"></script>
      <script src="docgen-resources/main.min.js"></script>
  </div>
<div class="col-right"><div class="page-content"><div class="page-title"><div class="pagers top"><a class="paging-arrow previous" href="versions_2_3_22.html"><span>Previous</span></a><a class="paging-arrow next" href="versions_2_3_20.html"><span>Next</span></a></div><div class="title-wrapper">
<h1 class="content-header header-section1" id="versions_2_3_21" itemprop="headline">2.3.21</h1>
</div></div><div class="page-menu">
<div class="page-menu-title">Page Contents</div>
<ul><li><a class="page-menu-link" href="#autoid_151" data-menu-target="autoid_151">Changes on the FTL side</a></li><li><a class="page-menu-link" href="#autoid_152" data-menu-target="autoid_152">Changes on the Java side</a></li><li><a class="page-menu-link" href="#autoid_153" data-menu-target="autoid_153">Other changes</a></li></ul> </div><p>Date of release: 2014-10-12</p><p>Note that since 2.3.21 is designed to be fully backward
        compatible with the previous 2.3.x releases, <em>some of the
        improvements and fixes described below are only activated when you
        specifically ask for 2.3.21 "incompatible
        improvements"</em>, because they could, with very small
        chance, break existing applications. If the dependent project is still
        actively developed, allowing 2.3.21 &quot;incompatible improvements&quot; is
        highly recommended. See <a href="pgui_config_incompatible_improvements.html#pgui_config_incompatible_improvements_how_to_set">how to set
        "incomplatible improvements" here</a>.</p><p>Note that we have changed our proprietary BSD-style license to
        Apache License, Version 2.0. See the <a href="app_license.html">new
        license here</a>.</p><p>Note that the minimum required Java version was increased from
        1.2 to 1.4.</p>
          



<h2 class="content-header header-section2" id="autoid_151">Changes on the FTL side</h2>


          <ul>
            <li>
              <p>Improved ranges:</p>

              <ul>
                <li>
                  <p>Added ranges with exclusive end:
                  <code class="inline-code"><em class="code-color">start</em>..&lt;<em class="code-color">end</em></code>
                  (also can be written as
                  <code class="inline-code"><em class="code-color">start</em>..!<em class="code-color">end</em></code>).
                  <a href="dgui_template_exp.html#dgui_template_exp_direct_ranges">More...</a></p>
                </li>

                <li>
                  <p>Added length limited ranges:
                  <code class="inline-code"><em class="code-color">start</em>..*<em class="code-color">length</em></code>:
                  For example, <code class="inline-code">10..*4</code> gives <code class="inline-code">[10,
                  11, 12, 13]</code>, <code class="inline-code">10..*-4</code> gives
                  <code class="inline-code">[10, 9, 8, 7]</code>, and
                  <code class="inline-code">10..*0</code> gives <code class="inline-code">[]</code>. When
                  these kind of ranges are used for slicing, the slice will
                  end without error if the end of the sliced sequence or
                  string is reached before the specified range length was
                  reached. Thus, for example, to take the first 10 characters
                  from the string <code class="inline-code">s</code>, or less if
                  <code class="inline-code">s</code> is shorter than 10 characters, you can
                  use <code class="inline-code">s[0..*10]</code>. <a href="dgui_template_exp.html#dgui_template_exp_seqenceop_slice">More...</a></p>
                </li>

                <li>
                  <p>Square bracket now accepts range values from any
                  source, like <code class="inline-code">&lt;#assign r = 1..3&gt;
                  ${&#39;foobar&#39;[r]}</code> will print
                  <code class="inline-code">&quot;oob&quot;</code>. Earlier it has only supported
                  ranges that were specified directly inside the square
                  brackets, like <code class="inline-code">&#39;foobar&#39;[1..3]</code>.</p>
                </li>

                <li>
                  <p>When slicing a sequence with a right-unbounded range,
                  it&#39;s now allowed to have a range start index that&#39;s one
                  higher than the last index of the sliced sequence. For
                  example, <code class="inline-code">[&#39;x&#39;, &#39;y&#39;][2..]</code> is not an error
                  anymore, but an empty sequence. (Of course, <code class="inline-code">[&#39;x&#39;,
                  &#39;y&#39;][3..]</code> is still an error.)</p>
                </li>

                <li>
                  <p><code class="inline-code"><em class="code-color">someString</em>?substring(<em class="code-color">from</em>,
                  <em class="code-color">toExclusive</em>)</code> and
                  <code class="inline-code"><em class="code-color">someString</em>?substring(<em class="code-color">from</em>)</code>
                  are now deprecated; use this slicing expression instead:
                  <code class="inline-code"><em class="code-color">someString</em>[<em class="code-color">from</em>..&lt;<em class="code-color">toExclusive</em>]</code>
                  and
                  <code class="inline-code"><em class="code-color">someString</em>[<em class="code-color">from</em>..]</code>.
                  A warning if you are processing XML: Since slicing
                  expressions work both for sequences and strings, and XML
                  nodes in FTL are typically both sequences and strings at the
                  same time, there the equivalent expression is
                  <code class="inline-code"><em class="code-color">someXmlNode</em>?string[<em class="code-color">from</em>..&lt;<em class="code-color">toExclusive</em>]</code>
                  and
                  <code class="inline-code"><em class="code-color">exp</em>?string[<em class="code-color">from</em>..]</code>,
                  because without the <code class="inline-code">?string</code> it would
                  slice the node sequence instead of the text value of the
                  node.</p>
                </li>

                <li>
                  <p>If the <code class="inline-code">incompatible_improvements</code> in
                  the FreeMarker configuration is set to at least 2.3.21,
                  right-unbounded ranges become readable (like
                  <code class="inline-code">#list</code>-able). Earlier they could only be
                  used for slicing, and behaved like empty sequences
                  otherwise.</p>
                </li>
              </ul>
            </li>

            <li>
              <p>New built-in, <code class="inline-code">?url_path</code>: This is the
              same as <a href="ref_builtins_string.html#ref_builtin_url">the
              <code>url</code> built-in</a>, except that it doesn&#39;t
              escape slash (<code class="inline-code">/</code>) characters. This meant to be
              used for converting paths (like paths coming from the OS or some
              content repository) that use slash (not backslash!) to a path
              the can be inserted into the path part of an URL.</p>
            </li>

            <li>
              <p>New built-ins for string manipulation:</p>

              <ul>
                <li>
                  <p><code class="inline-code"><em class="code-color">someString</em>?keep_before(<em class="code-color">substring</em>[,
                  <em class="code-color">flags</em>])</code>: <a href="ref_builtins_string.html#ref_builtin_keep_before">More...</a></p>
                </li>

                <li>
                  <p><code class="inline-code"><em class="code-color">someString</em>?keep_after(<em class="code-color">substring</em>[,
                  <em class="code-color">flags</em>])</code>: <a href="ref_builtins_string.html#ref_builtin_keep_after">More...</a></p>
                </li>

                <li>
                  <p><code class="inline-code"><em class="code-color">someString</em>?remove_beginning(<em class="code-color">substring</em>)</code>:
                  <a href="ref_builtins_string.html#ref_builtin_remove_beginning">More...</a></p>
                </li>

                <li>
                  <p><code class="inline-code"><em class="code-color">someString</em>?remove_ending(<em class="code-color">substring</em>)</code>:
                  <a href="ref_builtins_string.html#ref_builtin_remove_ending">More...</a></p>
                </li>

                <li>
                  <p><code class="inline-code"><em class="code-color">someString</em>?ensure_starts_with(<em class="code-color">substring</em>[,
                  <em class="code-color">substitution</em>[,
                  <em class="code-color">flags</em>]])</code>: <a href="ref_builtins_string.html#ref_builtin_ensure_starts_with">More...</a></p>
                </li>

                <li>
                  <p><code class="inline-code"><em class="code-color">someString</em>?ensure_ends_with(<em class="code-color">substring</em>)</code>:
                  <a href="ref_builtins_string.html#ref_builtin_ensure_ends_with">More...</a></p>
                </li>
              </ul>
            </li>

            <li>
              <p><code class="inline-code"><em class="code-color">someString</em>?number</code>
              now recognizes all XML Schema number formats, like
              <code class="inline-code">NaN</code>, <code class="inline-code">INF</code>,
              <code class="inline-code">-INF</code>, plus the Java-native formats
              <code class="inline-code">Infinity</code> and
              <code class="inline-code">-Infinity</code>.</p>
            </li>

            <li>
              <p>If <code class="inline-code">incompatible_improvements</code> in the
              FreeMarker configuration is set to at least 2.3.21,
              <code class="inline-code"><em class="code-color">someNumber</em>?c</code> will
              return <code class="inline-code">&quot;INF&quot;</code>, <code class="inline-code">&quot;-INF&quot;</code> and
              <code class="inline-code">&quot;NaN&quot;</code> for positive/negative infinity and IEEE
              floating point Not-a-Number, respectively. These are the XML
              Schema compatible representations of these special values.
              Earlier it has returned what
              <code class="inline-code">java.text.DecimalFormat</code> did with US locale,
              none of which was understood by any (common) computer
              language.</p>
            </li>

            <li>
              <p>New built-in:
              <code class="inline-code"><em class="code-color">someString</em>?boolean</code>.
              This is for example useful for converting &quot;true&quot; and &quot;false&quot;
              strings coming from XML to real boolean values. <a href="ref_builtins_string.html#ref_builtin_boolean">More...</a></p>
            </li>

            <li>
              <p>Date/time/date-time related changes:</p>

              <ul>
                <li>
                  <p>Added new kind of
                  <code class="inline-code">date_format</code>/<code class="inline-code">datetime_format</code>/<code class="inline-code">time_format</code>
                  setting values: XML Schema formats, starting with
                  <code class="inline-code">&quot;xs&quot;</code> and ISO 8601:2004 formats, starting
                  with <code class="inline-code">&quot;iso&quot;</code>. The format string can be
                  continued with various space (or <code class="inline-code">_</code>)
                  separated options, like <code class="inline-code">h</code> or
                  <code class="inline-code">m</code> or <code class="inline-code">s</code> or
                  <code class="inline-code">ms</code> for setting shown accuracy,
                  <code class="inline-code">nz</code> or <code class="inline-code">fz</code> for setting
                  time zone offset visibility, and <code class="inline-code">u</code> or,
                  <code class="inline-code">fu</code> for using UTC time zone . For example,
                  to use ISO 8601 with minute precision and without the zone
                  offset being shown, set the
                  <code class="inline-code">datetime_format</code> setting to <code class="inline-code">&quot;iso
                  m nz&quot;</code>, so then the output will be like
                  <code class="inline-code">2014-09-03T20:56</code>. <a href="ref_directive_setting.html#topic.dateTimeFormatSettings">More...</a></p>
                </li>

                <li>
                  <p>Because anything that&#39;s accepted as
                  <code class="inline-code">date_format</code>/<code class="inline-code">datetime_format</code>/<code class="inline-code">time_format</code>
                  setting value can also be used with the
                  <code class="inline-code">?string</code> and
                  <code class="inline-code">?date</code>/<code class="inline-code">?time</code>/<code class="inline-code">?datetime</code>
                  build-ins, you can use the new formats like
                  <code class="inline-code">someDate?string.xs</code> and
                  <code class="inline-code">someString?date.xs</code>. (For the
                  <code class="inline-code">&quot;xs&quot;</code> and <code class="inline-code">&quot;iso&quot;</code>
                  formats, <code class="inline-code">_</code> can be used instead of space,
                  which means that, for example, you can write
                  <code class="inline-code">lastModified?string.iso_m_u</code> instead of
                  the more verbose <code class="inline-code">lastModified?string[&quot;iso m
                  u&quot;]</code>.)</p>
                </li>

                <li>
                  <p>That <code class="inline-code">&quot;iso&quot;</code> and
                  <code class="inline-code">&quot;xs&quot;</code> are now possible
                  <code class="inline-code">date_format</code>/<code class="inline-code">datetime_format</code>/<code class="inline-code">time_format</code>
                  setting values also means that such values can now be parsed
                  too via
                  <code class="inline-code">?date</code>/<code class="inline-code">?time</code>/<code class="inline-code">?datetime</code>.
                  The main application is with processing XML DOM-s, as there
                  values are coming in as strings, and now you can do
                  something like <code class="inline-code">order.confirmDate?date.xs</code>
                  to convert them to real dates.</p>
                </li>

                <li>
                  <p>The <a href="ref_builtins_date.html#ref_builtin_date_iso"><code>?iso_...</code>
                  built-ins</a> are now deprecated in favor of the new
                  setting values described above. They can be set as the
                  default date/time/date-time format, seamlessly fit into the
                  formatting architecture (and thus can parse strings too),
                  and has more/better options (<code class="inline-code">ms</code> always
                  shows 3 millisecond digits, <code class="inline-code">fz</code> for
                  forcing showing time zone offset).</p>
                </li>

                <li>
                  <p>If the "incompatible improvements"
                  configuration setting is at least 2.3.21, the
                  <code class="inline-code">?iso_...</code> built-ins won&#39;t show time zone
                  offset for <code class="inline-code">java.sql.Time</code> values anymore.
                  Most databases store time values that aren&#39;t in any time
                  zone, but just store hour, minute, second, and decimal
                  second field values, so showing the time zone doesn&#39;t make
                  sense. (Notable exceptions are PostgreSQL &quot;time with time
                  zone&quot; columns, where
                  <code class="inline-code"><em class="code-color">mzTime</em>?string.iso_fz</code>
                  could be used.)</p>
                </li>

                <li>
                  <p>Added <code class="inline-code">?is_time</code>,
                  <code class="inline-code">?is_datetime</code>,
                  <code class="inline-code">?is_date_only</code> (should be called
                  <code class="inline-code">?is_date</code>, but that was already taken) and
                  <code class="inline-code">?is_unknown_date_like</code> to check the exact
                  type of a date-like value.</p>
                </li>

                <li>
                  <p><code class="inline-code">?is_date</code> is now a deprecated name,
                  use <code class="inline-code">?is_date_like</code> instead. This is
                  because <code class="inline-code">?is_date</code> sounds like it checks if
                  the value is a date without time part, but actually it also
                  returns <code class="inline-code">true</code> for time, date-time, and
                  unknown date-like values.</p>
                </li>

                <li>
                  <p>Added <code class="inline-code">?date_if_unknown</code>,
                  <code class="inline-code">?time_if_unknown</code> and
                  <code class="inline-code">?datetime_if_unknown</code> built-ins, which
                  mark a date-like value with some of the sub-types: date
                  without time, time, or date-time, respectively. However, if
                  the value already holds this information, the built-in has
                  no effect. That is, it will never convert the sub-type of a
                  value, it only adds the sub-type if it was unknown.</p>
                </li>

                <li>
                  <p>Bug fixed: ISO 8601 dates (via
                  <code class="inline-code">?iso_...</code> and <code class="inline-code">&quot;iso&quot;</code>
                  format settings) now use proleptic Gregorian calendar for
                  the years before 1582, rather than Julian calendar. This is
                  (indirectly) required by the standard, and it&#39;s also how the
                  default Sun/Oracle Java XML Schema date/time/dateTime parser
                  works.</p>
                </li>
              </ul>
            </li>

            <li>
              <p>Error message quality improvements (targeting frequent
              support requests and some error message bugs):</p>

              <ul>
                <li>
                  <p>Fixed glitch where if an <code class="inline-code">#if</code> had
                  and <code class="inline-code">#else</code> or <code class="inline-code">#elseif</code>,
                  the
                  <code class="inline-code">#if</code>/<code class="inline-code">#else</code>/<code class="inline-code">#elseif</code>
                  wasn&#39;t hidden in the FTL stack trace when the error was
                  inside its nested block.</p>
                </li>

                <li>
                  <p>Some new context sensitive hints in undefined variable
                  exception error messages.</p>
                </li>

                <li>
                  <p>Fixed unclosed directive error messages at end of file
                  where the wrong unclosed directive name was reported</p>
                </li>

                <li>
                  <p>Better type error messages when accessing XML data
                  (applies when wrapped with
                  <code class="inline-code">freemarker.ext.dom</code>):</p>

                  <ul>
                    <li>
                      <p>Trying to use
                      <code class="inline-code">node.<em class="code-color">noSuchChildNodes</em></code>
                      on a place where scalar value is expected will explain
                      that the problem is that you had no matches in the
                      constructing XML query.</p>
                    </li>

                    <li>
                      <p>Trying to use
                      <code class="inline-code">node.<em class="code-color">multipleSuchChildNodes</em></code>
                      on a place where scalar value is expected will explain
                      that the problem is that you had multiple matches in the
                      constructing XML query.</p>
                    </li>

                    <li>
                      <p>Trying to use
                      <code class="inline-code">node.<em class="code-color">exactlyOneChildNode</em></code>
                      as number, date/time/date-time or boolean will explain
                      that values coming from XML are always strings (text),
                      and must be converted explicitly via
                      <code class="inline-code">?number</code>, <code class="inline-code">?boolean</code>,
                      <code class="inline-code">?date.xs</code>, etc.</p>
                    </li>
                  </ul>
                </li>

                <li>
                  <p>Trying to use <code class="inline-code">obj.someMethod</code>
                  without <code class="inline-code">()</code> on a place where method value
                  is not expected will recommend calling the method.</p>
                </li>

                <li>
                  <p>Trying to use methods like
                  <code class="inline-code">obj.getFoo</code> or
                  <code class="inline-code">obj.isFoo</code> without <code class="inline-code">()</code>on
                  a place where method value is not expected will recommend
                  using the <code class="inline-code">obj.foo</code> form.</p>
                </li>

                <li>
                  <p>Messages are now much more readable when rendered in
                  environments that don&#39;t obey to line-breaks. (This often
                  happens in improperly implemented HTML error pages and logs
                  viewers.)</p>
                </li>

                <li>
                  <p>Better FTL instruction stack traces:</p>

                  <ul>
                    <li>
                      <p>Error messages now contain up to 10 lines of FTL
                      stack trace (unless it&#39;s on the top of a full FTL stack
                      trace), because the FTL stack trace wasn&#39;t printed at
                      all when the exception was a cause exception in a Java
                      stack trace, or when only the value of
                      <code class="inline-code">getMessage()</code> was printed instead of a
                      stack trace.</p>
                    </li>

                    <li>
                      <p>The FTL stack trace is now more self explanatory
                      as it contains more text labels.</p>
                    </li>

                    <li>
                      <p>Stack frames that belong to nestings are now
                      marked differently, and are filtered out when the stack
                      trace wouldn&#39;t fit into the error message
                      otherwise.</p>
                    </li>
                  </ul>
                </li>

                <li>
                  <p>Bug fixed: <code class="inline-code">?substring</code> has thrown
                  low level
                  <code class="inline-code">java.lang.IndexOutOfBoundsException</code>-s
                  instead of more descriptive
                  <code class="inline-code">TemplateModelException</code>-s with FTL stack
                  trace.</p>
                </li>

                <li>
                  <p>Bug fixed: Slicing with ranges sometimes thrown low
                  level
                  <code class="inline-code">java.lang.IndexOutOfBoundsException</code>-s
                  instead of more descriptive
                  <code class="inline-code">TemplateModelException</code>-s with FTL stack
                  trace.</p>
                </li>

                <li>
                  <p>Bug fixed [<a href="https://sourceforge.net/p/freemarker/bugs/402/">402</a>]:
                  Fixed misleading parser error message when a directive
                  called without its required parameters (like
                  <code class="inline-code">&lt;#list&gt;</code>) was reported as unknown
                  directive.</p>
                </li>

                <li>
                  <p>Bug fixed [<a href="http://sourceforge.net/p/freemarker/bugs/222/">222</a>]:
                  Poor quality error message when
                  <code class="inline-code"><em class="code-color">someString</em>[<em class="code-color">someIndex</em>]</code>
                  fails with string index out of bounds.</p>
                </li>

                <li>
                  <p>Bug fixed [<a href="http://sourceforge.net/p/freemarker/bugs/27/">27</a>]:
                  Not very good quality error messages when
                  <code class="inline-code">#import</code>-ing a template whose parsing
                  fails.</p>
                </li>
              </ul>
            </li>

            <li>
              <p>New <code class="inline-code">include</code> directive option,
              <code class="inline-code">ignore_missing=<em class="code-color">boolean</em></code>.
              When this is set to <code class="inline-code">true</code>, and the template to
              include is missing, the error will be silently ignored, and
              nothing will be included.</p>
            </li>

            <li>
              <p>The <code class="inline-code">setting</code> directive can now set the
              <code class="inline-code">output_encoding</code> setting.</p>
            </li>

            <li>
              <p>New special variable: <code class="inline-code">.locale_object</code>.
              This is like <code class="inline-code">.locale</code>, except that it&#39;s a
              <code class="inline-code">java.util.Locale</code> object, not a string. This
              is handy if you want to pass the current locale to Java
              methods.</p>
            </li>

            <li>
              <p>If <code class="inline-code">incompatible_improvements</code> in the
              FreeMarker configuration is set to at least 2.3.21, hash
              <em>literals</em> that repeat keys now only have the
              key once with <code class="inline-code">?keys</code>, and only has the last
              value associated to that key with <code class="inline-code">?values</code>.
              This is consistent with the behavior of
              <code class="inline-code"><em class="code-color">hash</em>[<em class="code-color">key</em>]</code>
              and how maps work in Java.</p>
            </li>

            <li>
              <p>Bug fixed: <code class="inline-code">?is_enumerable</code> has returned
              <code class="inline-code">true</code> for Java methods get from Java objects,
              despite that those values aren&#39;t <code class="inline-code">&lt;#list
              ...&gt;</code>-able. (This is actually a historical quirk of
              <code class="inline-code">BeansWrapper</code>, not a bug in
              <code class="inline-code">?is_enumerable</code>, but now
              <code class="inline-code">?is_enumerable</code> is aware of this exceptional
              case.)</p>
            </li>

            <li>
              <p>Bug fixed [<a href="http://sourceforge.net/p/freemarker/bugs/257/">257</a>]:
              The result value of <code class="inline-code">?matches</code> wasn&#39;t
              "reentrant". For example, you couldn&#39;t list the
              matches inside another listing where you are also listing
              exactly the same result value (stored in a common variable), as
              they would consume from the same iterator. Most importantly,
              even accessing the <code class="inline-code">?size</code> of the same result
              value has terminated the outer listing of the same value.</p>
            </li>

            <li>
              <p>Bug fixed [<a href="http://sourceforge.net/p/freemarker/bugs/229/">229</a>]:
              If you set <code class="inline-code">incompatible_improvements</code> to
              2.3.21 (or higher), unclosed comments (<code class="inline-code">&lt;#--
              <em class="code-color">...</em></code>) and
              <code class="inline-code">#noparse</code>-s won&#39;t be silently closed at the
              end of template anymore, but cause a parsing error
              instead.</p>
            </li>
          </ul>
        
          



<h2 class="content-header header-section2" id="autoid_152">Changes on the Java side</h2>


          <ul>
            <li>
              <p>Added new <code class="inline-code">Configuration</code> constructor,
              <code class="inline-code">Configuration(Version
              incompatibleImprovements)</code>. This deprecates the vague
              <code class="inline-code">Configuration()</code> constructor, and makes using
              <code class="inline-code">setIncompatibleImprovements(Version)</code> needless
              in most cases. See an example <a href="pgui_quickstart_createconfiguration.html">here...</a></p>
            </li>

            <li>
              <p>When setting the
              <code class="inline-code">incompatible_improvements</code> setting (like with
              the constructor above) to 2.3.21, two setting defaults
              change:</p>

              <ul>
                <li>
                  <p>The default of the <code class="inline-code">object_wrapper</code>
                  setting
                  (<code class="inline-code">Configuration.getObjectWrapper()</code>)
                  changes from
                  <code class="inline-code">ObjectWrapper.DEFAULT_WRAPPER</code> to another
                  almost identical <code class="inline-code">DefaultObjectWrapper</code>
                  singleton, returned by <code class="inline-code">new
                  DefaultObjectWrapperBuilder(Version).build()</code>. The
                  new default object wrapper&#39;s "incompatible
                  improvements" version is set to the same as of the
                  <code class="inline-code">Configuration</code>. (See later regarding the
                  2.3.21 "incompatible improvements" of
                  <code class="inline-code">BeansWrapper</code> and
                  <code class="inline-code">DefaultObjectWrapper</code>). Furthermore, the
                  new default object wrapper doesn&#39;t allow changing its
                  settings; setter methods will throw
                  <code class="inline-code">IllegalStateException</code>. (If anything tries
                  to call setters on the old default in your application,
                  that&#39;s a dangerous bug that won&#39;t remain hidden now. As the
                  old default is a singleton too, potentially shared by
                  independently developed components, most of them expects the
                  out-of-the-box behavior from it (and the others are
                  necessarily buggy). Also, then concurrency glitches can
                  occur (and even pollute the class introspection cache)
                  because the singleton is modified after publishing.)</p>
                </li>

                <li>
                  <p>The default of the <code class="inline-code">template_loader</code>
                  setting
                  (<code class="inline-code">Configuration.getTemplateLoader()</code>})
                  changes to <code class="inline-code">null</code>, which means that
                  FreeMarker will not find any templates. Earlier the default
                  was a <code class="inline-code">FileTemplateLoader</code> that used the
                  current directory as the root. This was dangerous and
                  fragile as you usually don&#39;t have good control over what the
                  current directory will be. Luckily, the old default almost
                  never looked for the templates at the right place anyway, so
                  pretty much all applications had to set
                  <code class="inline-code">template_loader</code>, so it&#39;s unlikely that
                  changing the default breaks your application.</p>
                </li>
              </ul>
            </li>

            <li>
              <p>New <code class="inline-code">BeansWrapper</code>,
              <code class="inline-code">DefaultObjectWrapper</code> and
              <code class="inline-code">SimpleObjectWrapper</code> constructor that takes a
              <code class="inline-code">Version</code>
              <code class="inline-code">incompatibleImprovements</code> argument. This has
              the same role as the
              <code class="inline-code">incompatible_improvements</code> setting of the
              <code class="inline-code">Configuration</code>, but it applies to the
              <code class="inline-code">ObjectWrapper</code> instead. (As
              <code class="inline-code">ObjectWrapper</code>-s are often shared among
              multiple <code class="inline-code">Configuration</code>-s, so they can&#39;t use
              that setting of the <code class="inline-code">Configuration</code>.) In new or
              actively developed projects it&#39;s recommended to use
              <code class="inline-code">Configuration.VERSION_2_3_21</code> now. The
              constructor without the <code class="inline-code">Version</code> parameter is
              now deprecated.</p>
            </li>

            <li>
              <p>Safer and more memory-efficient way of managing singletons
              of <code class="inline-code">DefaultObjectWrapper</code>-s and
              <code class="inline-code">BeansWrapper</code>-s that are possibly shared by
              independently developed subsystems:</p>

              <ul>
                <li>
                  <p>Instead of <code class="inline-code">new
                  DefaultObjectWrapper(<em class="code-color">...</em>)</code>
                  and <code class="inline-code">new
                  BeansWrapper(<em class="code-color">...</em>)</code>, from
                  now on you should use <code class="inline-code">new
                  DefaultObjectWrapperBuilder(version).build()</code> and
                  <code class="inline-code">new BeansWrapperBuilder(version).build()</code>.
                  (The builder objects have properties (configuration
                  settings) like <code class="inline-code">BeansWrapper</code> has, which
                  specify the properties of the objects created.) The created
                  objects are <em>singletons</em> (VM-wide, or at
                  least Web-Application-wide) and read-only (means,
                  non-configurable, hence safe to share). The main benefit of
                  using these factories instead of creating new instances is
                  that it allows FreeMarker to share the class introspection
                  caches (an internal part of
                  <code class="inline-code">BeansWrapper</code>-s/<code class="inline-code">DefaultObjectWrapper</code>-s
                  that is expensive to populate) among the returned instances.
                  This allow sharing the caches (and the object wrappers)
                  between components that aren&#39;t aware of each other and use
                  FreeMarker internally.</p>
                </li>

                <li>
                  <p>Deprecated the static fields
                  <code class="inline-code">ObjectWrapper.DEFAULT_WRAPPER</code>,
                  <code class="inline-code">BEANS_WRAPPER</code> and
                  <code class="inline-code">SIMPLE_WRAPPER</code>, because these
                  <code class="inline-code">ObjectWrapper</code>-s are configurable (not
                  read-only), and thus dangerous to use as singletons (a badly
                  behaving 3rd party component can mess them up). Use the
                  factories described above instead. They are also more
                  flexible, as you can specify the desired
                  incompatible-improvements version for them and various other
                  <code class="inline-code">BeansWrapper</code> settings.</p>
                </li>

                <li>
                  <p>Deprecated all <code class="inline-code">SimpleHash</code>,
                  <code class="inline-code">SimpleCollection</code> and
                  <code class="inline-code">SimpleSequence</code> constructors that didn&#39;t
                  take an <code class="inline-code">ObjectWrapper</code> argument, as they
                  have usually used
                  <code class="inline-code">ObjectWrapper.DEFAULT_WRAPPER</code> as the
                  default, which itself is deprecated.</p>
                </li>

                <li>
                  <p><code class="inline-code">BeansWrapper</code>,
                  <code class="inline-code">DefaultObjectWrapper</code> and
                  <code class="inline-code">SimpleObjectWrapper</code> now implements the
                  <code class="inline-code">freemarker.template.utility.WriteProtectable</code>
                  interface with which the configuration properties of the
                  object wrapper can be set permanently to read-only by
                  calling <code class="inline-code">writeProtect()</code>. An attempt to
                  call a setter on a such <code class="inline-code">ObjectWrapper</code>
                  will immediately cause
                  <code class="inline-code">IllegalStateException</code>. (This is what&#39;s
                  used for the singletons returned by the
                  <code class="inline-code">getInstance</code> methods too; see
                  earlier).</p>
                </li>
              </ul>
            </li>

            <li>
              <p>The value of the <code class="inline-code">time_zone</code> setting,
              when you specify it with a <code class="inline-code">String</code> (in a
              <code class="inline-code">java.util.Properties</code> object, or via
              <code class="inline-code">&lt;#setting
              <em class="code-color">...</em>&gt;</code>) can now be
              <code class="inline-code">&quot;JVM default&quot;</code> to use the JVM default time
              zone. The JVM default is the default value of that setting
              anyway, but now you can state this explicitly, or restore this
              value if it was overridden earlier.</p>
            </li>

            <li>
              <p>Added new configuration setting,
              <code class="inline-code">sql_date_and_time_time_zone</code>
              (<code class="inline-code">Configurable.setSQLDateAndTimeTimeZone(TimeZone)</code>).
              When this is set to non-<code class="inline-code">null</code>, the time zone
              used when dealing with <code class="inline-code">java.sql.Date</code> and
              <code class="inline-code">java.sql.Time</code> values will be this time zone
              instead of the value of the <code class="inline-code">time_zone</code>
              FreeMarker configuration setting. This is useful because JDBC
              will, usually, construct the Java <code class="inline-code">Date</code>
              objects so that they will show the year-month-day and
              hour-minute-seconds values from the database "as
              is" if you render them using the JVM default time zone.
              As time zone conversions for SQL date-only and SQL time-only
              values doesn&#39;t make much sense (unlike for SQL timestamps), you
              should certainly set this setting to the JVM default time zone
              (<code class="inline-code">TimeZone.getDefault()</code>, or if you configure
              FreeMarker via <code class="inline-code">java.util.Properties</code>, as
              property value &quot;JVM default&quot;). The default value is
              <code class="inline-code">null</code> for backward compatibility. For more
              details see the JavaDoc of
              <code class="inline-code">Configurable.setSQLDateAndTimeTimeZone(TimeZone)</code>.</p>
            </li>

            <li>
              <p>When configuring FreeMarker with
              <code class="inline-code">java.util.Properties</code> (typically, when the
              configuration is stored in a <code class="inline-code">.properties</code>
              file), for the settings where you could specify a fully
              qualified class name (most notably for the
              <code class="inline-code">object_wrapper</code> setting) now you can also
              specify constructor arguments and JavaBean property assignments.
              For example, now you can write
              <code class="inline-code">object_wrapper=com.example.MyObjectWrapper(1, 2,
              exposeFields=true, cacheSize=5000)</code>that&#39;s nearly
              equivalent with this Java code: <code class="inline-code">obj = new
              com.example.MyObjectWrapper(1, 2); obj.setExposeFields(true);
              obj.setCacheSize(5000); object_wrapper = obj;</code>. If you
              are using this new syntax (i.e., if you have parentheses after
              the class name, even if they are empty), and there&#39;s a builder
              class for the requested class, that will be automatically used.
              For example,
              <code class="inline-code">object_wrapper=DefaultObjectWrapper(2.3.21)</code>
              will create a <code class="inline-code">DefaultObjectWrapperBuilder</code> to
              build the final instance, thus the object wrapper will be a
              singleton instead of a new instance. The new syntax will also
              look for a public static <code class="inline-code">INSTANCE</code> field if
              there are 0 arguments and property assignments. For more details
              see the Java API documentation of
              <code class="inline-code">Configuration.setSetting</code>.</p>
            </li>

            <li>
              <p>Template not found exceptions now explain that the
              template path is interpreted by a template loader, and show the
              <code class="inline-code">toString</code> of the
              <code class="inline-code">TemplateLoader</code>. The out-of-the-box
              <code class="inline-code">TemplateLoader</code> implementations now have an
              overridden <code class="inline-code">toString</code> to show the actual base
              directory and such details. Custom
              <code class="inline-code">TemplateLoader</code> implementations are encouraged
              to override <code class="inline-code">toString</code>.</p>
            </li>

            <li>
              <p>Added
              <code class="inline-code">Configuration.setSharedVariables(Map/*&lt;String,
              Object&gt;*/)</code> for setting the shared variables from
              Spring IoC and other IoC solutions. The already existing
              <code class="inline-code">Configuration.setSharedVariable(String,
              Object)</code> isn&#39;t a JavaBean property so it was hard to
              use for that. Furthermore, the order in which
              <code class="inline-code">Configuration.setObjectWrapper</code> and
              <code class="inline-code">Configuration.setSharedVariables</code> are called
              doesn&#39;t mater (unlike in the case of
              <code class="inline-code">Configuration.setSharedVariable</code>), which is
              essential in most IoC solutions.</p>
            </li>

            <li>
              <p>Mostly concerning tool (like IDE plugin) authors:</p>

              <ul>
                <li>
                  <p><code class="inline-code">ParseException</code>-s now also store the
                  end-location of the error, not just its start-location. This
                  is useful if you want to underline the error in the source
                  code, not just point at it.</p>
                </li>

                <li>
                  <p><code class="inline-code">Configuration.getSupportedBuiltInDirectiveNames()</code>
                  can be used to return the names of directives supported by
                  FreeMarker.</p>
                </li>

                <li>
                  <p><code class="inline-code">TemplateExceptions</code> now expose the
                  position of the error (template name, line, column, end
                  line, end column) similarly to
                  <code class="inline-code">ParseException</code>-s. Where applicable, they
                  also expose the blamed expression in its canonical FTL
                  source form; this is mostly useful for
                  <code class="inline-code">InvalidReferenceException</code>-s.</p>
                </li>
              </ul>
            </li>

            <li>
              <p>The concurrent performance of overloaded method lookups
              (from the cache) was improved under Java 5 and later.</p>
            </li>

            <li>
              <p>The <code class="inline-code">Version</code> instances that are
              "incompatible improvements" break points are now
              available via constants like:
              <code class="inline-code">Configuration.VERSION_2_3_21</code>.</p>
            </li>

            <li>
              <p>From now on, if you try to set the "incompatible
              improvements" to greater than the current FreeMarker
              version, or less than 2.3.0, an
              <code class="inline-code">IllegalArgumentException</code> will be thrown.
              Thus, <code class="inline-code">new
              Configuration(<em class="code-color">someVersion</em>)</code>
              not only activates the fixes up to that version, but ensures
              that the application will not run in an environment with an
              older FreeMarker version. (On an older FreeMarker version the
              improvements that you have requested aren&#39;t implemented yet, so
              you should get an exception.)</p>
            </li>

            <li>
              <p>Added new configuration setting,
              <code class="inline-code">show_error_tips</code>, defaults to
              <code class="inline-code">true</code>. Sets if tips should be shown in error
              messages of errors arising during template processing.</p>
            </li>

            <li>
              <p>Instead of overriding
              <code class="inline-code">BeansWrapper.finetuneMethodAppearance</code> (now
              deprecated), now you can use
              <code class="inline-code">BeansWrapper.setMethodAppearanceFineTuner(MethodAppearanceFineTuner)</code>,
              so you don&#39;t need to extend the object wrapper class to
              customize this aspect.</p>
            </li>

            <li>
              <p>Added
              <code class="inline-code">Configuration.getCoreDirecticeNames()</code> which
              returns the names of all directives that are provided by
              FreeMarker. This can useful for IDE-s.</p>
            </li>

            <li>
              <p><code class="inline-code">template_loader</code> was added as possible
              configuration setting <code class="inline-code">Properties</code> key.</p>
            </li>

            <li>
              <p>The standard <code class="inline-code">CacheStorage</code>
              implementations now have a <code class="inline-code">getSize()</code> method
              for monitoring the cache size.
              <code class="inline-code">MruCacheStorage</code> also has
              <code class="inline-code">getSoftSize()</code> and
              <code class="inline-code">getStrongSize()</code>.</p>
            </li>

            <li>
              <p>Various smaller improvements in configuration setting
              errors messages.</p>
            </li>

            <li>
              <p>With incompatible improvements 2.3.21 only: Empty ranges
              return <code class="inline-code">Constants.EMPTY_SEQUENCE</code> instead of an
              empty <code class="inline-code">SimpleSequence</code>. This is in theory
              backward compatible, as the API only promises to give something
              that implements <code class="inline-code">TemplateSequenceModel</code>.</p>
            </li>

            <li>
              <p>FreeMarker now requires Java version has changed from 1.2
              to 1.4.</p>
            </li>

            <li>
              <p>Bugs fixed and improvements in overloaded method
              selection/invocation, but only if you create the
              <code class="inline-code">BeansWrapper</code>/<code class="inline-code">DefaultObjectWrapper</code>
              with constructor parameter
              <code class="inline-code">Configuration.VERSION_2_3_21</code> (or if you are
              using <code class="inline-code">Properties</code> to configure FreeMarker, you
              can do that like
              <code class="inline-code">object_wrapper=BeansWrapper(2.3.21)</code>), or if
              you have a <code class="inline-code">Configuration</code> with similar
              <code class="inline-code">incompatible_improvements</code> 2.3.21
              <em>and</em> you leave the
              <code class="inline-code">object_wrapper</code> setting on its default value.
              There&#39;s a little chance that because of these changes, a
              different overloaded method will be chosen than before, or even
              that ambiguity errors will arise where earlier they didn&#39;t
              (although the opposite is far more frequent), hence the fixes
              aren&#39;t automatically activated. But the fix mostly only effect
              calls that were failing or have chosen then wrong method
              earlier, so it&#39;s recommended to activate it for projects that
              are still actively developed. This fix includes numerous
              changes:</p>

              <ul>
                <li>
                  <p>Earlier, <code class="inline-code">null</code> argument values has
                  only matched overloaded methods where the corresponding
                  parameter had <code class="inline-code">Object</code> type, not a subclass
                  of it. That&#39;s clearly a bug. Now it considers all overloads
                  where the parameter type is non-primitive, and just like the
                  Java language, it choses the one with the most specific type
                  among them. This is the most important fix, and also the
                  most risky one regarding backward-compatibility. Like if you
                  have <code class="inline-code">m(Object o)</code> and <code class="inline-code">m(String
                  s)</code> in a Java class, earlier for a
                  <code class="inline-code">m(null)</code> call in the template it has
                  chosen <code class="inline-code">m(Object o)</code>, but now it will
                  choose <code class="inline-code">m(String s)</code> instead (because
                  <code class="inline-code">String</code> is also
                  <code class="inline-code">null</code>-able and is more specific than
                  <code class="inline-code">Object</code>). Furthermore, if you also had
                  <code class="inline-code">m(File f)</code> in the same class, now it will
                  cause an ambiguity exception, since the specificity of
                  <code class="inline-code">File</code> and <code class="inline-code">String</code> can&#39;t
                  be compared (same rule as under Java language), while
                  earlier that wasn&#39;t a problem as only <code class="inline-code">m(Object
                  o)</code> was seen as applicable.</p>
                </li>

                <li>
                  <p>The behavior of numbers with overloaded method
                  selection was heavily reworked:</p>

                  <ul>
                    <li>
                      <p>If possible, it now always choses the overload
                      where overflow and truncation to integer (like 1.5 to 1)
                      is avoided. Among the methods where no such critical
                      loss occurs, it choses the overload with the least risk
                      of precision loss (unless other conditions with higher
                      priority suggest otherwise). Earlier, the method
                      selection was prone to do choices that led to overflow
                      or precision loss, especially when the parameter was a
                      literal with decimals.</p>
                    </li>

                    <li>
                      <p>Overloaded method call can now convert to
                      non-primitive numerical types, like a
                      <code class="inline-code">Byte</code> or <code class="inline-code">byte</code> value
                      is automatically converted to <code class="inline-code">Integer</code>
                      if the parameter type is <code class="inline-code">Integer</code>.
                      (This has always worked for non-overloaded methods.)
                      Earlier where such conversion was needed, the method
                      wasn&#39;t seen seen applicable.</p>
                    </li>

                    <li>
                      <p>Method selection is now not only based on the type
                      of the wrapped number, but also on its value. For
                      example, a <code class="inline-code">Long</code> with value
                      <code class="inline-code">1</code> is now seen as compatible with a
                      method with parameter type <code class="inline-code">int</code> or
                      <code class="inline-code">short</code> or <code class="inline-code">byte</code>, as
                      <code class="inline-code">1</code> can be stored in those without
                      loss. This is important as unlike in Java language, in
                      FTL you doesn&#39;t have strict control over the numerical
                      types (the type of the wrapped number, actually), as FTL
                      has no type declarations. (If multiple compatible
                      methods are available, it will still try to chose the
                      one with the same or bigger numerical type.)</p>
                    </li>

                    <li>
                      <p>Conversion from/to <code class="inline-code">BigInteger</code>
                      is now supported.</p>
                    </li>
                  </ul>
                </li>

                <li>
                  <p>Method choice ambiguity errors now occur much less
                  often. Ambiguities was and are resolved by selecting the
                  compatible methods then choosing the one with the most
                  specific parameter types among them. The changes are:</p>

                  <ul>
                    <li>
                      <p>When comparing the overall specificity of two
                      parameter lists: Earlier the parameter list seen as more
                      specific was the one that had some parameters that won
                      in specificity, and if both had such parameters then it
                      was an ambiguity. Now it&#39;s enough if a method has more
                      such parameters where it&#39;s a better match than the other
                      has, or if the two methods are still equal, if it has
                      the first better matching parameter. This can lead to
                      choices that seem arbitrary (but are still
                      deterministic), but as there&#39;s no automated way of
                      discovering method selection ambiguities in templates
                      (unlike in Java source code, where they will be detected
                      during compilation), especially as overloaded selection
                      has to rely on the <em>runtime</em> type of
                      the values which even make proper testing hard, this was
                      considered to be a better compromise than throwing an
                      exception whenever the choice of the method is not
                      obvious. Also note that in fact this mechanism is more
                      complicated than just counting the "winner"
                      parameter positions for each methods, as certain kind of
                      wins are stronger than any number of the others: wins
                      where the other possibility is risking of substantial
                      mantissa precision loss are the strongest (like dropping
                      decimals versus not to), wins where the primitive type
                      wins over the boxed class is the weakest (like
                      <code class="inline-code">int</code> versus
                      <code class="inline-code">Integer</code>), subclassing wins (like
                      <code class="inline-code">String</code> versus
                      <code class="inline-code">Object</code>) are between these two.</p>
                    </li>

                    <li>
                      <p>When comparing the specificity of two parameters
                      types at the same parameter position: The algorithm now
                      considers a primitive type as more specific that its
                      corresponding boxing class (like <code class="inline-code">int</code>
                      is considered to be more specific than
                      <code class="inline-code">Integer</code>).</p>
                    </li>

                    <li>
                      <p>There was a bug with overloaded varargs methods of
                      different parameter counts, where sometimes the last
                      parameters of the compared methods was ignored, which is
                      taking away a potential deciding factor and thus can
                      lead to ambiguity error. Whether this happened depends
                      on the order in which the Java reflection API has
                      returned the methods, which is undocumented and known to
                      change at least after some Java updates, breaking the
                      application.</p>
                    </li>

                    <li>
                      <p>When comparing the specificity of two array types,
                      until now they were seen as equal. Now the component
                      types are compared, and then that with the less specific
                      component type is preferred. For example, among
                      <code class="inline-code">f(String[])</code> and
                      <code class="inline-code">f(Object[])</code>, the last will always
                      win. This might sounds controversial, but as we can&#39;t
                      efficiently tell the common type of all the items in a
                      sequence or <code class="inline-code">List</code>, an so we don&#39;t know
                      if both arrays are indeed valid targets, we go for the
                      safest choice.</p>
                    </li>
                  </ul>
                </li>

                <li>
                  <p>FTL sequence values (like Java
                  <code class="inline-code">List</code>-s or FTL
                  <code class="inline-code">[<em class="code-color">x</em>,
                  <em class="code-color">y</em>,
                  <em class="code-color">...</em>]</code> constants) were
                  not seen as applicable to a parameter with array type if
                  there were multiple overloaded methods with the same number
                  of parameters but with different types on the position of
                  the array parameter. That is, if you had
                  <code class="inline-code">f(String[])</code> and
                  <code class="inline-code">f(String)</code> in Java, then
                  <code class="inline-code">f([&#39;foo&#39;, &#39;bar&#39;])</code> in the template
                  reported no compatible overloads. Now it will choose
                  <code class="inline-code">f(String[])</code>. Note that if there&#39;s also an
                  <code class="inline-code">f(List)</code> or even an
                  <code class="inline-code">f(Collection)</code>, it will prefer those over
                  arrays. (For consistency, this conversion will work even if
                  the argument is a <code class="inline-code">List</code> that come directly
                  from Java (as opposed to be created inside FTL), i.e., when
                  it was wrapped then unwrapped to the original
                  <code class="inline-code">List</code> object.) For a multidimensional
                  array parameter type, this conversion works recursively, so
                  you can pass in a sequence-of-sequences as the
                  argument.</p>
                </li>

                <li>
                  <p>FTL sequence values that wrapped a Java array (when
                  FreeMarker was also aware of that via
                  <code class="inline-code">AdapterTemplateModel</code> or
                  <code class="inline-code">WrapperTemplateModel</code>) were not seen as
                  applicable to a parameter with <code class="inline-code">List</code> type
                  if there were multiple overloaded methods with the same
                  number of parameters but with different types on the
                  position of the array parameter. So this is pretty much like
                  the issue described in the previous point, but for array to
                  <code class="inline-code">List</code> conversion. The array to
                  <code class="inline-code">List</code> conversion will be avoided if
                  possible, but it will be attempted if there&#39;s no other
                  alternative. Note that unlike with <code class="inline-code">List</code>
                  to array conversions, here FreeMarker can&#39;t cope with
                  multi-dimensional lists, that is, an array-of-arrays won&#39;t
                  be converted to a
                  <code class="inline-code">List</code>-of-<code class="inline-code">List</code>-s.</p>
                </li>

                <li>
                  <p>FTL string to Java
                  <code class="inline-code">char</code>/<code class="inline-code">Character</code>
                  conversion now works for overloaded method parameters;
                  earlier it has worked for non-overloaded methods only. If
                  the string length is 1, it will be seen as compatible with
                  parameters with <code class="inline-code">char</code> or
                  <code class="inline-code">Character</code> type.</p>
                </li>

                <li>
                  <p>Decreased the chance of choosing the wrong target Java
                  type when unwrapping multi-typed FTL values: When unwrapping
                  a parameter value that implements multiple FTL types (e.g.
                  string and hash) but doesn&#39;t implement
                  <code class="inline-code">AdapterTemplateModel</code> or
                  <code class="inline-code">WrapperTemplateModel</code>, a decision has to
                  be made if to what Java type the value should be unwrapped
                  to (e.g. to <code class="inline-code">String</code> or to
                  <code class="inline-code">Map</code>). In earlier versions that decision
                  was made based on the most specific common super type of the
                  parameters types of the given parameter position. However,
                  it&#39;s quite common that the common super type is too generic,
                  usually <code class="inline-code">Object</code>. Now
                  <code class="inline-code">BeansWrapper</code> stores "type
                  flags" for each parameter position of overloaded
                  methods, from which it can tell whether a potential target
                  Java type occurs in any of the overloads on the given
                  parameter position.</p>
                </li>

                <li>
                  <p>In many cases, less specific hint class was used for
                  unwrapping than that was possible within the limitations of
                  the applied hint generation algorithm. (The unwrapping hint
                  has influence when there&#39;s an ambiguity regarding how to
                  create a Java object form an FTL value. In the vast majority
                  of the cases, a too generic hint has no effect.) (This is a
                  highly technical topic. The way it works is that a single
                  common unwrapping hint class is chosen for a given argument
                  position shared by the overloads that has the same number of
                  parameters, and that hint class has to be as specific as
                  possible while it must fit all those parameter types. The
                  issue with the too generic hints had several instances: (a)
                  When the most specific common class/interface of two
                  same-position parameter types was searched, if there was
                  multiple common classes/interfaces that had no relationship
                  (this is always at most one class and one or more unrelated
                  interfaces), due to the ambiguity it has felt back to using
                  <code class="inline-code">Object</code> as the unwrapping hint. Now if
                  there&#39;s a non-<code class="inline-code">Object</code> class among them in
                  such case, it will be chosen as the hint (i.e., we ignore
                  the common interfaces). Otherwise if only a single interface
                  remains by removing <code class="inline-code">Cloneable</code>,
                  <code class="inline-code">Serializable</code>, and
                  <code class="inline-code">Comparable</code> (in that order), that will be
                  chosen. Only then it falls back to
                  <code class="inline-code">Object</code>. (b) The common most specific
                  class of a primitive type and the corresponding boxing class
                  was sometimes <code class="inline-code">Object</code> instead of the
                  boxing class. This has depended on Java&#39;s internal ordering
                  of the methods, and so were quite unpredictable, like the
                  result could change after upgrading Java under the
                  application. (c) The common superclass of a numerical
                  primitive value and a numerical non-primitive value was
                  always <code class="inline-code">Object</code>, now if they are a
                  primitive-boxing class pair, then it&#39;s the boxing class,
                  otherwise it&#39;s <code class="inline-code">Number</code>. (d) If the varags
                  parameter position was not the same in all the overloaded
                  varargs methods, sometimes some varargs arguments where
                  unwrapped with too generic hints. When this happened was
                  unpredictable as it depended on Java&#39;s internal method
                  ordering again.)</p>
                </li>

                <li>
                  <p>When unwrapping method call arguments before calling a
                  Java method, if the argument was an
                  <code class="inline-code">AdapterTemplateModel</code> and the target
                  parameter type was primitive,
                  <code class="inline-code">AdapterTemplateModel.getAdaptedObject(Class
                  hint)</code> has received the primitive type of the
                  target parameter (like <code class="inline-code">int</code> instead of
                  <code class="inline-code">Integer</code>) as the hint. This did not make
                  sense since <code class="inline-code">getAdaptedObject</code> can only
                  return <code class="inline-code">Object</code>-s, not primitive values.
                  Yet, <code class="inline-code">BeansWrapper</code> has expected the
                  returned value to be of the primitive type, otherwise it has
                  discarded it. Exactly the same problem occurs with
                  <code class="inline-code">WrapperTemplateModel</code>. Thus, ultimately,
                  if the target parameter type was primitive and some of these
                  interfaces were implemented, their return value was always
                  discarded and FreeMarker has felt back to other means of
                  unwrapping. Now <code class="inline-code">BeansWrapper</code> always
                  passes in and expects the boxing type (like
                  <code class="inline-code">Integer</code>) instead of the primitive
                  type.</p>
                </li>
              </ul>
            </li>

            <li>
              <p>Bug fixed [<a href="http://sourceforge.net/p/freemarker/bugs/373/">373</a>]:
              These are three bugs actually, which can cause problems when
              FreeMarker re-loads a template because of a charset override
              with <code class="inline-code">&lt;#ftl encoding=&quot;...&quot;&gt;</code>: First, if
              the template loader was a <code class="inline-code">URLTemplateLoader</code>,
              when <code class="inline-code">TemplateLoader.getReader()</code> was called
              for the second time, and the <code class="inline-code">Reader</code> returned
              for the first time was already used, it might returned an empty
              or corrupted template, depending on the backing URL
              implementation. Secondly, when FreeMarer has decided if a
              template file has to be re-loaded because its encoding specified
              with <code class="inline-code">&lt;#ftl encoding=&quot;...&quot;&gt;</code> differs from
              the encoding used for loading the template first, it has used
              case-sensitive comparison, thus often re-loaded needlessly (like
              &quot;UTF-8&quot; and &quot;utf-8&quot; mean the same). Now this comparison is
              case-insensitive. Last not least, when retrying with the second
              charset, the <code class="inline-code">TemplateCache</code> has forgotten to
              close the first <code class="inline-code">Reader</code>, which can be a handle
              leak.</p>
            </li>

            <li>
              <p>Bug fixed [<a href="http://sourceforge.net/p/freemarker/bugs/411/">411</a>]:
              Invalid and redundant execution environment names from the OSGi
              bundle manifest were removed. It looks like this now:
              <code class="inline-code">Bundle-RequiredExecutionEnvironment: J2SE-1.5,
              J2SE-1.4</code>. That is, we prefer (and compile against)
              1.5, but only require 1.4.</p>
            </li>

            <li>
              <p>Bug fixed [<a href="http://sourceforge.net/p/freemarker/bugs/409/">409</a>]:
              <code class="inline-code">SimpleHash</code>&#39;s internal <code class="inline-code">Map</code>
              is concurrently modified on a non-safe way when getting length-1
              <code class="inline-code">String</code> key that exists but maps to
              <code class="inline-code">null</code>. This operation will accidentally add a
              <code class="inline-code">Character</code> key to the internal map, which is
              not a thread-safe operation.</p>
            </li>

            <li>
              <p>Bug fixed [<a href="http://sourceforge.net/p/freemarker/bugs/273/">273</a>]:
              <code class="inline-code">TemplateLoader</code>-s that use
              <code class="inline-code">java.net.URLConnection</code>-s should set
              <code class="inline-code">URLConnection.useCaches</code> to
              <code class="inline-code">false</code>, or else it won&#39;t detect template
              caches on certain configurations.</p>

              <ul>
                <li>
                  <p><code class="inline-code">URLTemplateLoader</code> and its
                  subclasses and
                  <code class="inline-code">WebApplicationTemplateLoader</code> now has a
                  <code class="inline-code">setURLConnectionUsesCaches(Boolean)</code>
                  method. It&#39;s recommended to set this property to
                  <code class="inline-code">false</code> from its default backward
                  compatible value, <code class="inline-code">null</code>. As FreeMarker has
                  its own template cache with its own update delay setting
                  (<code class="inline-code">template_update_delay</code>,
                  <code class="inline-code">Configuration.setTemplateUpdateDelay(int)</code>),
                  it shouldn&#39;t cause performance problems. The
                  <code class="inline-code">null</code> value will leave the caching of the
                  <code class="inline-code">java.net.URLConnection</code> on its default,
                  which is usually <code class="inline-code">true</code>.</p>
                </li>

                <li>
                  <p>If <code class="inline-code">incompatible_improvements</code> is set
                  to 2.3.21 (or higher) and templates are loaded through
                  <code class="inline-code">Configuration.getTemplate</code>, and the
                  <code class="inline-code">TemplateLoader</code> in use has
                  <code class="inline-code">URLConnectionUsesCaches</code> left on
                  <code class="inline-code">null</code>, it will behave as if it was set to
                  <code class="inline-code">false</code>. Note that this
                  <code class="inline-code">incompatible_improvements</code> trick only
                  works if the template is loaded through
                  <code class="inline-code">Configuration.getTemplate</code> (or
                  <code class="inline-code">TemplateCache</code>).</p>
                </li>
              </ul>
            </li>

            <li>
              <p>Bug fixed: When changing the properties of
              <code class="inline-code">DefaultObjectWrapper</code> or
              <code class="inline-code">BeansWrapper</code> that influenced class
              introspection results (like <code class="inline-code">exposureLevel</code> or
              <code class="inline-code">exposeFields</code>), the introspection cache wasn&#39;t
              cleared, and thus returned stale information for the classes
              that were introspected before those properties were changed. Now
              changing such properties always clears the introspection
              caches.</p>
            </li>

            <li>
              <p>Bug fixed: Constants used for empty sequence, empty hash,
              empty collection and empty iterator weren&#39;t
              <code class="inline-code">Serializable</code>.</p>
            </li>

            <li>
              <p>Bug fixed [<a href="http://sourceforge.net/p/freemarker/bugs/311/">300</a>]:
              Logger class availability check was incorrect in that it has
              checked the availability of logger libraries with the thread
              context class loader, then later it tried to link to them with
              the defining class loader of the FreeMarker classes. With some
              class loader setups (notably under Netbeans sometimes) this led
              to <code class="inline-code">ClassDefNotFoundError</code>-s that made
              FreeMarker unusable. (The check itself was also not very
              durable, as it didn&#39;t expected <code class="inline-code">LinakeError</code>-s,
              only <code class="inline-code">ClassNotFoundException</code>.)</p>
            </li>

            <li>
              <p>Bug fixed: <code class="inline-code">ClassUtil.forName</code>, used
              inside FreeMarker everywhere to resolve class names to classes,
              if the thread context class loader is <code class="inline-code">null</code>,
              no longer tries to load with the bootstrap class loader before
              loading with the defining class loader of FreeMarker.</p>
            </li>

            <li>
              <p>Bug fixed [<a href="http://sourceforge.net/p/freemarker/bugs/311/">311</a>]:
              <code class="inline-code">TemplateBooleanModel.TRUE</code> and
              <code class="inline-code">FALSE</code> are now serializable</p>
            </li>

            <li>
              <p>Bug fixed: Various issues in <code class="inline-code">Version</code>
              class, such as wrong <code class="inline-code">hashCode</code>, possible
              concurrency glitches, and acceptance of some malformed version
              strings.</p>
            </li>

            <li>
              <p>Bug fixed [<a href="https://sourceforge.net/p/freemarker/bugs/414/">414</a>]:
              Eclipse debug mode running was suspended during FreeMarker
              static initialization on the JRebel availability checked if
              JRebel wasn&#39;t available.</p>
            </li>
          </ul>
        
          



<h2 class="content-header header-section2" id="autoid_153">Other changes</h2>


          <ul>
            <li>
              <p>The license has changed from our proprietary BSD-Style
              license to the well know &quot;Apache License, Version 2.0&quot;.
              Furthermore, the copyright owner has changed from &quot;Visigoth
              Software Society&quot; (which was founded by Jonathan Revusky) to the
              three main FreeMarker 2 developers/contributors, &quot;Attila
              Szegedi, Daniel Dekany, and Jonathan Revusky&quot;. See the <a href="app_license.html">new license here</a>.</p>
            </li>

            <li>
              <p>The required minimum Java version was raised from 1.2 to
              1.4. FreeMarker will not work on Java 1.2 or 1.3.</p>
            </li>

            <li>
              <p>Many smaller improvements and fixes in the Manual and API
              JavaDocs.</p>
            </li>
          </ul>
        <div class="bottom-pagers-wrapper"><div class="pagers bottom"><a class="paging-arrow previous" href="versions_2_3_22.html"><span>Previous</span></a><a class="paging-arrow next" href="versions_2_3_20.html"><span>Next</span></a></div></div></div></div>      </div>
    </div>
<div class="site-footer"><div class="site-width"><div class="footer-top"><div class="col-left sitemap"><div class="column"><h3 class="column-header">Overview</h3><ul><li><a href="http://freemarker.org/index.html">What is FreeMarker?</a></li><li><a href="http://freemarker.org/freemarkerdownload.html">Download</a></li><li><a href="app_versions.html">Version history</a></li><li><a href="http://freemarker.org/history.html">About us</a></li><li><a itemprop="license" href="app_license.html">License</a></li></ul></div><div class="column"><h3 class="column-header">Handy stuff</h3><ul><li><a href="http://freemarker-online.kenshoo.com/">Try template online</a></li><li><a href="dgui_template_exp.html#exp_cheatsheet">Expressions cheatsheet</a></li><li><a href="ref_directive_alphaidx.html">#directives</a></li><li><a href="ref_builtins_alphaidx.html">?built_ins</a></li><li><a href="ref_specvar.html">.special_vars</a></li></ul></div><div class="column"><h3 class="column-header">Community</h3><ul><li><a href="https://github.com/nanlei/freemarker/tree/manual-zh-2.3-gae/src/manual">Chinese Manual on Github</a></li><li><a href="https://github.com/freemarker/freemarker">FreeMarker on Github</a></li><li><a href="https://twitter.com/freemarker">Follow us on Twitter</a></li><li><a href="https://sourceforge.net/p/freemarker/bugs/new/">Report a bug</a></li><li><a href="http://stackoverflow.com/questions/ask?tags=freemarker">Ask a question</a></li><li><a href="http://freemarker.org/mailing-lists.html">Mailing lists</a></li></ul></div></div><div class="col-right"><ul class="social-icons"><li><a class="github" href="https://github.com/freemarker/freemarker">Github</a></li><li><a class="twitter" href="https://twitter.com/freemarker">Twitter</a></li><li><a class="stack-overflow" href="http://stackoverflow.com/questions/ask?tags=freemarker">Stack Overflow</a></li></ul><a class="xxe" href="http://www.xmlmind.com/xmleditor/" rel="nofollow" title="Edited with XMLMind XML Editor"><span>Edited with XMLMind XML Editor</span></a></div></div><div class="footer-bottom"><p><span class="generated-for-product">Generated for: Freemarker 2.3.23</span><span class="last-updated"> Last generated:
<time itemprop="dateModified" datetime="2015-09-18T14:38:51Z" title="Friday, September 18, 2015 2:38:51 PM GMT">2015-09-18 14:38:51 GMT</time></span></p> <p class="copyright">
© <span itemprop="copyrightYear">1999</span>–2015
<a itemtype="http://schema.org/Organization" itemprop="copyrightHolder" href="http://freemarker.org">The FreeMarker Project</a>. All rights reserved. </p>
</div></div></div></body>
</html>
